package com.example.schooldaka.util;


import cn.hutool.log.Log;
import com.sun.jndi.toolkit.url.UrlUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.apache.http.impl.client.CloseableHttpClient;

import javax.net.ssl.SSLContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;

/**
 * @program: SchoolDaKa
 * @description: 登录工具类
 * @author: Mr.Gui
 * @create: 2022-01-10 19:08
 **/
public class LoginUtil {

    public static Result getLoginSession(String username, String password,String address) throws Exception {
        int stateCode = 200;
        int count = 0;
        HttpResponse loginHttpResponse = null;
        HttpResponse execute = HttpRequest.get("https://cas.gzccc.edu.cn/lyuapServer/login?service=http://hqfw.gzccc.edu.cn/").execute();
        String body = execute.body();
        Map<String, List<String>> headers = execute.headers();
        // 获取JSESSIONID
        List<String> strings = headers.get("Set-Cookie");
        String session = strings.get(0).replace("JSESSIONID=", "").replace("; Path=/lyuapServer/; Secure; HttpOnly", "");
        // 获取lt
        String lt = body.substring(body.indexOf("\"lt\" value=\"") + "\"lt\" value=\"".length(), body.indexOf(".example.org") + ".example.org".length());
        // 获取 execution
        String execution = body.substring(body.indexOf("\"execution\" value=\"") + "\"execution\" value=\"".length(), body.indexOf("<input type=\"hidden\" name=\"_eventId\"")).replace("\" />", "").trim();
        // 获取到正确的验证码为止
        while (stateCode == 200) {
            count++;
            HttpRequest captchaHttpRequest = HttpRequest.get("https://cas.gzccc.edu.cn/lyuapServer/captcha.jsp")
                    .header("Cookie", "JSESSIONID=" + session);
            InputStream inputStream = captchaHttpRequest.execute().bodyStream();
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\jar\\autoDaKa\\captcha\\captcha.png");
            byte buffer[] = new byte[1024];
            int length;
            int byteRead = 0;
            while ((byteRead = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, byteRead);
            }
            LoginUtil loginUtil = new LoginUtil();
            if ( loginUtil.doOrc().length() != 4) {
                continue;
            }
            String captcha =  loginUtil.doOrc();
            // 第一次 模拟登录
            String postBody = "username=" + username + "&password=" + loginUtil.getEncryptionPassword(password) + "&captcha=" + captcha + "&warn=true&lt=" + lt + "&execution=" + execution + "&_eventId=submit";
            loginHttpResponse = HttpRequest.post("https://cas.gzccc.edu.cn/lyuapServer/login?service=http://hqfw.gzccc.edu.cn/")
                    .body(postBody)
                    .header("host", "cas.gzccc.edu.cn")
                    .header("Cookie", "JSESSIONID=" + session)
                    .header("Referer", "https://cas.gzccc.edu.cn/lyuapServer/login?service=http://hqfw.gzccc.edu.cn/")
                    .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
                    .header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1")
                    .execute();
            if (loginHttpResponse.body().indexOf("此帐户已被锁定") != -1) {
                return Result.fail("error,此帐户已被锁定");
            }
            if (loginHttpResponse.body().indexOf("账号或密码错误") != -1) {
                return Result.fail("error,账号或密码错误");
            }
            if (loginHttpResponse.getStatus() != 200) {
                // 验证码正确
                stateCode = loginHttpResponse.getStatus();
            }
        }
        Map<String, List<String>> firstHeaders = loginHttpResponse.headers();
        String location = firstHeaders.get("Location").get(0);
        // 第二次 获取http请求地址
        HttpResponse httpRequest = HttpRequest.get(location)
                .header("host", "hqfw.gzccc.edu.cn")
                .header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1")
                .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
                .execute();

        Map<String, List<String>> headers2 = httpRequest.headers();
        List<String> location2 = headers2.get("Location");
        // 第三次 再次跳转
        String url = location2.get(0);
        HttpResponse httpRequest3 = HttpRequest.get(url)
                .header("host", "hqfw.gzccc.edu.cn")
                .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
                .header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1")
                .execute();
        Map<String, List<String>> headers3 = httpRequest3.headers();
        // 第四次请求
        List<String> cookie = headers3.get("Set-Cookie");
        String session2 = cookie.get(0).replace("PHPSESSID=", "").replace("; path=/; HttpOnly", "").trim();
        HttpResponse fourResult = HttpRequest.get("https://hqfw.gzccc.edu.cn/")
                .header("host", "hqfw.gzccc.edu.cn")
                .header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1")
                .header("Cookie", "JSESSIONID=" + session2)
                .execute();
        if (fourResult.getStatus() == 200) {
            // 获取到Session
            String phpSession = session2;
            String data = sendGetRequest("https://hqfw.gzccc.edu.cn/m/jkdk/add.html",phpSession);
            try{
                String __token__ = data.substring(data.indexOf("name=\"__token__\" value=\"") + "name=\"__token__\" value=\"".length(), data.indexOf("\" />", data.indexOf("name=\"__token__\" value=\"")));
                String student_name = data.substring(data.indexOf("name=\"student_name\" value=\"") + "name=\"student_name\" value=\"".length(), data.indexOf("\">", data.indexOf("name=\"student_name\" value=\"")));
                String mobile = data.substring(data.indexOf("name=\"mobile\" value=\"") + "name=\"mobile\" value=\"".length(), data.indexOf("\">", data.indexOf("name=\"mobile\" value=\"")));
                String postData = "__token__=" + __token__+ "&mobile=" + mobile+"&student_health=0&student_symptom=&family_health=0&family_symptom=&high_risk_area=0&high_risk_area_title=&id=&student_name="+ student_name +"&location=" + UrlUtil.encode(address,"utf-8").toUpperCase();
                String result = sendPostRequest("https://hqfw.gzccc.edu.cn/m/jkdk/add.html", phpSession, postData);
                String state = result.substring(result.indexOf("<h2 class=\"weui-msg__title\">") + "<h2 class=\"weui-msg__title\">".length(), result.indexOf("</h2>", result.indexOf("<h2 class=\"weui-msg__title\">")));
                System.out.println(state);
                return Result.success(state);
            }catch (Exception e){
                return Result.fail("异常",e);
            }


        } else {
            return Result.fail("请联系管理员处理");
        }

    }

    /**
     * 识别验证码
     *
     * @return
     * @throws TesseractException
     */
    public String doOrc() throws TesseractException {
        //识别样本输出地址
//        String ocrResult = "C:\\Users\\root\\Desktop\\SchoolDaKa\\captcha\\captcha.png";
        String ocrResult = "D:\\jar\\autoDaKa\\captcha\\captcha.png";
        ITesseract instance = new Tesseract();
//        instance.setDatapath("D:\\orcDataTess\\tessdata");
//        System.out.println("地址" + System.getProperty("user.dir") + "/tessdata");
        instance.setDatapath("D:\\jar\\autoDaKa\\tessdata");
        File imgDir = new File(ocrResult);
        String code = instance.doOCR(imgDir);//识别验证码
        return code.trim();
    }

    /**
     * 加密密码
     * @param password
     * @return
     * @throws Exception
     */
    public String getEncryptionPassword(String password) throws Exception {
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine engine = scriptEngineManager.getEngineByName("javascript");
        FileReader fileReader = new FileReader(new File("D:\\jar\\autoDaKa\\rsaJs\\RSA.js"));
//        FileReader fileReader = new FileReader(new File(this.getClass().getResource("/rsaJs/RSA.js").getPath()));
        engine.eval(fileReader);
        engine.eval(new FileReader(new File("D:\\jar\\autoDaKa\\rsaJs\\BigInt.js")));
//        engine.eval(new FileReader(new File(this.getClass().getResource("/rsaJs/BigInt.js").getPath())));
//        engine.eval(new FileReader(new File(this.getClass().getResource("/rsaJs/Barrett.js").getPath())));
        engine.eval(new FileReader(new File("D:\\jar\\autoDaKa\\rsaJs\\Barrett.js")));
        engine.eval("setMaxDigits(131)");
        engine.eval("key = new RSAKeyPair(\"10001\",\"\",\"0083c618634d0de6fcfd8fb08c19251880397c260db7c36d789b1e8dc9a423b4cb972a4a175a1b26091770c51954f516d77bb3875c39f01aa13a7f9ef41e675649eb0a6297f7654fac6f473bf5d721bfb34a933f9e85e19b53fbae0dabb7d876fe960fcaca5b6c1b2b3879e0ad94dd1f96b97bf9ec1c443e9da64f9e17f0e36687\")");
        String result = (String) engine.eval("encryptedString(key, encodeURIComponent(\"" + password + "\"))");
        return result;
    }


    public static String sendPostRequest(String url, String session, String body) throws Exception {
        StringBuilder response = new StringBuilder();
        try {
            SSLContext sslContext = new SSLContextBuilder()
                    .loadTrustMaterial(null, (x509CertChain, authType) -> true)
                    .build();
            CloseableHttpClient httpClient = HttpClientBuilder.create()
                    .setSSLContext(sslContext)
                    .setConnectionManager(
                            new PoolingHttpClientConnectionManager(
                                    RegistryBuilder.<ConnectionSocketFactory>create()
                                            .register("http", PlainConnectionSocketFactory.INSTANCE)
                                            .register("https", new SSLConnectionSocketFactory(sslContext,
                                                    NoopHostnameVerifier.INSTANCE))
                                            .build()
                            ))
                    .build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Cookie", "koo_6212dfc___forward__=/m/jkdk/index; PHPSESSID=" + session);
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            httpPost.setEntity(new StringEntity(body));
            //执行请求
            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                HttpEntity entity = httpResponse.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return response.toString();
    }

    public static String sendGetRequest(String url, String session) {
        StringBuilder response = new StringBuilder();
        try {
            SSLContext sslContext = new SSLContextBuilder()
                    .loadTrustMaterial(null, (x509CertChain, authType) -> true)
                    .build();
            CloseableHttpClient httpClient = HttpClientBuilder.create()
                    .setSSLContext(sslContext)
                    .setConnectionManager(
                            new PoolingHttpClientConnectionManager(
                                    RegistryBuilder.<ConnectionSocketFactory>create()
                                            .register("http", PlainConnectionSocketFactory.INSTANCE)
                                            .register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE))
                                            .build()
                            ))
                    .build();
            HttpGet httpPost = new HttpGet(url);
            httpPost.setHeader("Cookie", "PHPSESSID=" + session);
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            //执行请求
            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                HttpEntity entity = httpResponse.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return response.toString();
    }

}
